package com.sti.framework.core.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sti.framework.core.mybatis.MybatisTools;
import com.sti.framework.core.web.GlobalException;
import com.sti.framework.core.web.Page;
import com.sti.framework.core.web.ResponseBodyEntity;
import com.sti.framework.core.web.SimplePage;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 基础Service类
 * @param <M>
 * @param <T>
 */
public class BaseService<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> {

    /**
     * 有条件-有分页查询
     *
     * @param Page 分页相关信息，同IPage。同时可以处理请求参数，转化为搜索条件。
     * @param searchWhere 搜索内容
     * @return
     */
    public SimplePage<T> getListPage(Page<T> Page, Object searchWhere) {
        Page<T> list = super.getBaseMapper().selectPage(Page, MybatisTools.getQueryWrapper(searchWhere));
        return new SimplePage(list.getRecords(), list.getTotal(),list.getCurrent(),list.getSize());
    }
    public SimplePage<T> getListPage(Page<T> Page, LambdaQueryWrapper<T> searchWhere) {
        Page<T> list = super.getBaseMapper().selectPage(Page, searchWhere);
        return new SimplePage(list.getRecords(), list.getTotal(),list.getCurrent(),list.getSize());
    }
    public SimplePage<T> getListPage(Page<T> Page, QueryWrapper<T> searchWhere) {
        Page<T> list = super.getBaseMapper().selectPage(Page, searchWhere);
        return new SimplePage(list.getRecords(), list.getTotal(),list.getCurrent(),list.getSize());
    }

    /**
     * 无条件-有分页查询
     * @param Page 分页相关信息，同IPage。同时可以处理请求参数，转化为搜索条件。
     * @return
     */
    public SimplePage<T> getListPage(Page<T> Page) {
        Page<T> list = super.page(Page);
        return new SimplePage(list.getRecords(), list.getTotal(),list.getCurrent(),list.getSize());
    }

    /**
     * 有条件-无分页查询1
     *
     * @return
     */
    public List<T> getList(QueryWrapper<T> wrapper) {
        List<T> list = baseMapper.selectList(wrapper);
        return list;
    }
    public List<T> getList(LambdaQueryWrapper<T> wrapper) {
        List<T> list = baseMapper.selectList(wrapper);
        return list;
    }
    public List<T> getList(Object searchWhere) {
        List<T> list = baseMapper.selectList(MybatisTools.getQueryWrapper(searchWhere));
        return list;
    }

    /**
     * 无条件-无分页查询
     *
     * @return
     */
    public List<T> getList() {
        return super.list();
    }

    /**
     * 根据id查询一条数据
     *
     * @param id
     * @return
     */
    public T get(Long id) {
        return super.getById(id);
    }

    /**
     * 插入数据
     * @param obj
     */
    public void create(T obj) {
        super.save(obj);
    }

    /**
     * 更新数据(全部属性)
     * @param obj
     */
    @Transactional(value = "transactionManager")
    public void update(T obj, Long id) {
        T old = this.get(id);
        BeanUtils.copyProperties(obj, old, new String[]{"id"});
        super.updateById(old);
    }
    public void update(T obj) {
        super.updateById(obj);
    }

    /**
     * 更新数据(不更新null属性)
     * @param obj
     */
    @Transactional(value = "transactionManager")
    public void updateNotNull(T obj, Long id) {
        T old = this.get(id);
        String[] nullProperties = getNullProperties(obj);
        BeanUtils.copyProperties(obj, old, nullProperties);
        super.updateById(old);
    }

    /**
     * 根据id删除数据（逻辑删除）
     * @param id
     */
    public Boolean delete(Long id){
        T oObj = get(id);
        if (oObj == null) throw new GlobalException(ResponseBodyEntity.ResponseStatus.USER_ERROR_22101);
        return super.removeById(oObj);
    }

    public static String[] getNullProperties(Object src) {
        //1.获取Bean
        BeanWrapper srcBean = new BeanWrapperImpl(src);

        //2.获取Bean的属性描述
        PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();

        //3.获取Bean的空属性
        Set properties = new HashSet<>();
        for (PropertyDescriptor propertyDescriptor : pds) {
            String propertyName = propertyDescriptor.getName();
            Object propertyValue = srcBean.getPropertyValue(propertyName);
            if (StringUtils.isEmpty(propertyValue)) {
                srcBean.setPropertyValue(propertyName, null);
                properties.add(propertyName);
            }
        }
        properties.add("id");
        properties.add("fakeId");
        properties.add("creatorId");
        return (String[]) properties.toArray(new String[0]);
    }
}
